#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <signal.h>
#include <iconv.h>
#include <time.h>
#include <sys/time.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include "transform.h"
#include "scanner.h"
#include "syscore.h"
#include "apis.h"
#include "modules.h"
#include "common.h"

using namespace std;
MODREG modScannerInfo = {MODULE_SCANNER, TRUE, TRUE, 1000,NULL};	// 1s 
#define SCANNER_HB_INTERVAL 5000
void *scannerheartBeat = NULL;

extern bool query_lte_cell_info(int32_t sms_serial_fd,CMGRMI_INFO *cmgrmi_info, char* band_prefered);
extern bool query_wcdma_cell_info(int32_t sms_serial_fd,CRUS_INFO *crus_info);
extern bool query_gsm_cell_info(int32_t sms_serial_fd,MONI_INFO *moni_info);
void buildAndSendTlvCmdSetScannerResponseMsg(MSGHEADER *msgHdr, PCMDHEADER pCmd, U32 result, U32 paraType, U32 paraValue);

const char *modem_serial_dev[] = {"/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2", "/dev/ttyUSB3", "/dev/ttyUSB4"};
int32_t dongle_at_port = 2;
int32_t serial_fd = -1;

#define FREQLIST   7
const char *frequencyList[FREQLIST] = 
{
    "1", //telecom
    "1,3", //maybe unicom
    "3", //unicom
    "38", //cmcc
    "39", //cmcc
    "40", //cmcc
    "41"  //cmcc
};

LteSnifferResult lteCellInfo;
WcdmaSnifferResult wcdmaCellInfo;

int32_t open_serial_port(int32_t port_num)
{
    int32_t fd = open(modem_serial_dev[port_num], O_RDWR | O_NOCTTY | O_NDELAY);
    if( -1 == fd ) 
    {
        SCANNERLogError("can't open serial sort %s", modem_serial_dev[port_num]);

        return (-1);
    }

    /* test tty */
    if( isatty(STDIN_FILENO) == 0 )
    {
        SCANNERLogError("standard input is not a terminal device");
    }
    else
    {
        SCANNERLogInfo("standard input is a tty");
    }

    SCANNERLogInfo("open serial port %s done, get fd = %d", modem_serial_dev[port_num], fd);

    return fd;
}

int32_t set_serial_opt(int32_t fd, int32_t nSpeed, int32_t nBits, char nEvent, int32_t nStop)
{
    struct termios newtio, oldtio;
    if( tcgetattr(fd, &oldtio) != 0 )
    {                       
        SCANNERLogError("get fd(%d) attribute failed", fd);   
        return -1;
    }

    bzero(&newtio, sizeof (newtio));
    /* Active CLOCAL and CREAD */
    newtio.c_cflag |= CLOCAL | CREAD;

    switch( nSpeed )
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    case 460800:
        cfsetispeed(&newtio, B460800);
        cfsetospeed(&newtio, B460800);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }

    /* Set data bit */
    newtio.c_cflag &= ~CSIZE;
    switch( nBits ) 
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch( nEvent )
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }
  
    if( nStop == 1 )
    {
        newtio.c_cflag &= ~CSTOPB;
    }
    else if (nStop == 2)
    {
        newtio.c_cflag |= CSTOPB;
    }

    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;

    /* flush buffered data which are not sent yet */
    tcflush(fd, TCIFLUSH);

    /* Apply the new setting now */
    if( (tcsetattr(fd, TCSANOW, &newtio)) != 0 )
    { 
        SCANNERLogError("set fd(%d) attribute failed", fd);
        return -1;
    }

    SCANNERLogInfo("set serial port option done");
    return 0;
}

bool sc_init_serial(int32_t port_num)
{
    serial_fd = open_serial_port(port_num);
    if( serial_fd < 0 )
    {
        SCANNERLogError("open serial port failed");

        return false;
    }

    if( set_serial_opt(serial_fd, 115200, 8, 'N' , 1) < 0 )
    {
        SCANNERLogError("set serial option failed");

        return false;
    }
    return true;
}

void sc_term_serial()
{
    sleep(3);
    close(serial_fd);
    serial_fd = -1;
}

void buildLteSniffResult(MSGHEADER *msgHdr, PCMDHEADER pCmd)
{
    LTE_CELL_INFO *cellInfo = NULL;

    std::string qm = "\"";
    stringstream result;
    //build sniffer result to FEP

    //start
	result << "[";
    //build sniffer report
    bool teleValid = true;
    bool unccValid = true;
    for(uint32_t i = 0; i < lteCellInfo.cellNum; i++)
    {
        if(lteCellInfo.cell[i].earfcn == 1825)
        {
            teleValid = false;
        }
        
        if(lteCellInfo.cell[i].earfcn == 1650)
        {
            unccValid = false;
        }
    }

    if(teleValid)
    {
        cellInfo = &lteCellInfo.cell[lteCellInfo.cellNum];

        memcpy(cellInfo->plmn, "46011", 5);
        cellInfo->earfcn = 1825;
        lteCellInfo.cellNum++;
    }

    if(unccValid)
    {
        cellInfo = &lteCellInfo.cell[lteCellInfo.cellNum];

        memcpy(cellInfo->plmn, "46001", 5);
        cellInfo->earfcn = 1650;
        lteCellInfo.cellNum++;
    }

    for(uint32_t i = 0; i < lteCellInfo.cellNum; i++)
    {
        cellInfo = &lteCellInfo.cell[i];
        result << "{";
       	result << qm << "cellNumber" << qm << ":" << 1 << ",";
		result << qm << "plmn" << qm << ":" << cellInfo->plmn << ",";
		result << qm << "tac" << qm << ":" << cellInfo->tac << ",";
		result << qm << "earfcn" << qm << ":" << cellInfo->earfcn << ",";
		result << qm << "pci" << qm << ":" << cellInfo->pci << ",";
		result << qm << "rsrq" << qm << ":" << (int32_t)cellInfo->rsrq << ",";
		result << qm << "rsrp" << qm << ":" << (int32_t)cellInfo->rsrp << ",";
		result << qm << "rssi" << qm << ":" << (int32_t)cellInfo->rssi << ",";
		result << qm << "priority" << qm << ":" << (uint32_t)cellInfo->priority;

		result << "}";

 		if(i == (lteCellInfo.cellNum - 1))  continue;

		result << ",";
    }
	result << "]";
    result << endl;

    if(msgHdr->srcID == MODULE_INTF)
    {
	    CM_SendMsg_1Para(MODULE_INTF, MODULE_SCANNER, MSG_TYPE_COMMAND, CMD_EVENT, CMD_LTE_EVT_SNIFF, 0,
					     PARA_TYPE_SNIFFER_RESULT, result.str().length(), (U8 *)result.str().c_str());        
    }
	else
	{
	    CM_SendMsg_1Para(msgHdr->srcID, MODULE_SCANNER, MSG_TYPE_COMMAND, CMD_GET_RESPONSE, pCmd->cmdCode, pCmd->cmdIndex,
                         PARA_TYPE_SNIFFER_RESULT, result.str().length(), (U8 *)result.str().c_str());
	}

    return;
}

bool get_lte_cell_info(MSGHEADER *msgHdr, PCMDHEADER pCmd)
{
    char* bands = NULL;

    CMGRMI_INFO cmgrmi_info;
    memset(&cmgrmi_info, 0, sizeof(CMGRMI_INFO));
    CMGRMI_INFO *cmgrmi_info_ptr = &cmgrmi_info;

    uint64_t band = 0;
    uint64_t bs[64] = {0};        
    int band_num = 0;

    if (!sc_init_serial(dongle_at_port))
    {
        return false;
    }
 
    LTE_CELL_INFO *cellInfo = NULL;
    for(int i = 0; i < FREQLIST; i++)
    {
        band = 0;
        memset(bs, 0, sizeof(uint64_t) * 64);
        bands = (char *)frequencyList[i];

        if (bands)
        {
            band_num = sscanf(bands, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu", &bs[0],&bs[1],&bs[2],&bs[3],&bs[4],&bs[5],&bs[6],&bs[7],&bs[8],&bs[9], &bs[10],&bs[11],&bs[12],&bs[13],&bs[14],&bs[15],&bs[16],&bs[17],&bs[18],&bs[19], &bs[20],&bs[21],&bs[22],&bs[23],&bs[24],&bs[25],&bs[26],&bs[27],&bs[28],&bs[29], &bs[30],&bs[31],&bs[32],&bs[33],&bs[34],&bs[35],&bs[36],&bs[37],&bs[38],&bs[39], &bs[40],&bs[41],&bs[42],&bs[43],&bs[44],&bs[45],&bs[46],&bs[47],&bs[48],&bs[49], &bs[50],&bs[51],&bs[52],&bs[53],&bs[54],&bs[55],&bs[56],&bs[57],&bs[58],&bs[59], &bs[60],&bs[61],&bs[62],&bs[63]);
            for (int j = 0; j < band_num; j++)
            {
                uint64_t bin = bs[j] - 0x1ull;
                band = band | (0x1ull << bin);
            }
        }

        if (!query_lte_cell_info(serial_fd, &cmgrmi_info, band))
        {
            SCANNERLogError("failed to get cell info");
        }

        CMGRMI_MAIN_INFO *main_info = &(cmgrmi_info_ptr->main_info);
        if(main_info->service_available && main_info->valid)
        {
            uint8_t     plmn[8] = {0};
            uint16_t    tac = 0;
            uint32_t    cellNum = 0;
            bool        valid = true;
 
            CMGRMI_SERVING_CELL *serving_cell = &(cmgrmi_info_ptr->serving_cell);
            SCANNERLogDebug("Serving_Cell %d,%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", serving_cell->earfcn, serving_cell->mcc, serving_cell->mnc, serving_cell->tac, serving_cell->num_mnc_digits,serving_cell->serving_cell_id, serving_cell->freq_band_ind, serving_cell->dl_bandwidth, serving_cell->ul_bandwidth, serving_cell->serv_rssnr, serving_cell->cell_pci, serving_cell->cell_rsrq, serving_cell->cell_rsrp, serving_cell->cell_rssi, serving_cell->cell_idle_srxlev);

            memcpy(plmn, serving_cell->mcc, 3);
            memcpy(plmn + 3, serving_cell->mnc, 2);

            tac = serving_cell->tac;
            if(serving_cell->earfcn == 0) continue;

            CMGRMI_LTE_INTRA *lte_intra = &(cmgrmi_info_ptr->lte_intra);
            for(uint32_t j= 0; j < lte_intra->num_lte_cells; j++)
            {
                CMGRMI_LTE_INTRA_CELL *lte_intra_cell = &cmgrmi_info_ptr->lte_intra_cell[j];
                SCANNERLogDebug("LTE_Intra_Cell%d %d,%d,%d,%d,%d\n", j+1, lte_intra_cell->cell_pci, lte_intra_cell->cell_rsrq, lte_intra_cell->cell_rsrp, lte_intra_cell->cell_rssi, lte_intra_cell->cell_idle_srxlev);

                cellNum = lteCellInfo.cellNum;
                for(uint32_t k = 0; k < cellNum; k++)
                {
                    cellInfo = &lteCellInfo.cell[k];
                    SCANNERLogDebug("cellInfo earfcn %d, pci %d", cellInfo->earfcn, cellInfo->pci);
                    if(lte_intra_cell->cell_pci ==  cellInfo->pci && serving_cell->earfcn ==  cellInfo->earfcn)
                    {
                        cellInfo++;
                        valid = false;
                        break;
                    }
                }
                    
                if(valid)
                {
                    cellInfo = &lteCellInfo.cell[lteCellInfo.cellNum];
                    memcpy(cellInfo->plmn, plmn, sizeof(plmn));
                    cellInfo->tac = tac;
                    cellInfo->earfcn = serving_cell->earfcn;
                    cellInfo->pci = lte_intra_cell->cell_pci;
                    cellInfo->rsrq = lte_intra_cell->cell_rsrq / 10;
                    cellInfo->rsrp = lte_intra_cell->cell_rsrp / 10;
                    cellInfo->rssi = lte_intra_cell->cell_rssi / 10;
                    lteCellInfo.cellNum++;
                }

                valid = true;
            }

            CMGRMI_LTE_INTER *lte_inter = &(cmgrmi_info_ptr->lte_inter);
            SCANNERLogDebug("LTE_Inter %d,Freq1,%d,%d,%d,%d,%d,Freq2,%d,%d,%d,%d,%d\n", lte_inter->num_freqs, lte_inter->Freq1.earfcn, lte_inter->Freq1.num_lte_cells, lte_inter->Freq1.idle_threshX_low, lte_inter->Freq1.idle_threshX_high, lte_inter->Freq1.idle_cell_resel_priority, lte_inter->Freq2.earfcn, lte_inter->Freq2.num_lte_cells, lte_inter->Freq2.idle_threshX_low, lte_inter->Freq2.idle_threshX_high, lte_inter->Freq2.idle_cell_resel_priority);

            if( lte_inter->num_freqs == 0) continue;

            cellNum = lteCellInfo.cellNum;
            for(uint32_t k = 0; k < cellNum; k++)
            {
                cellInfo = &lteCellInfo.cell[k];
                if(lte_inter->Freq1.earfcn == cellInfo->earfcn || lte_inter->Freq1.earfcn == 0)
                {
                    cellInfo++;
                    valid = false;
                    break;
                }
            }

            if(valid)
            {
                 cellInfo = &lteCellInfo.cell[lteCellInfo.cellNum];
                 memcpy(cellInfo->plmn, plmn, sizeof(plmn));
                 cellInfo->tac = tac;
                 cellInfo->earfcn = lte_inter->Freq1.earfcn;
                 cellInfo->priority = lte_inter->Freq1.idle_cell_resel_priority;
                 lteCellInfo.cellNum++;
            }
            valid = true;

            cellNum = lteCellInfo.cellNum;
            for(uint32_t k = 0; k < cellNum; k++)
            {
                cellInfo = &lteCellInfo.cell[k];
                if(lte_inter->Freq2.earfcn == cellInfo->earfcn || lte_inter->Freq2.earfcn == 0)
                {
                    cellInfo++;
                    valid = false;
                    break;
                }
            }

            if(valid)
            {
                 cellInfo = &lteCellInfo.cell[lteCellInfo.cellNum];
                 memcpy(cellInfo->plmn, plmn, sizeof(plmn));
                 cellInfo->tac = tac;
                 cellInfo->earfcn = lte_inter->Freq2.earfcn;
                 cellInfo->priority = lte_inter->Freq2.idle_cell_resel_priority;
                 lteCellInfo.cellNum++;
            }
        }
    }
    
    sc_term_serial();
    return true;
}

void generateWcdmaSnifferResult(CRUS_INFO *crus_info)
{
    CRUS_INFO *crus_info_ptr = crus_info;
    SCANNERLogDebug("generateWcdmaSnifferResult active set %d", crus_info_ptr->active_set_cells_num);

    if(crus_info_ptr->active_set_cells_num > 0)
    {
        WCDMA_CELL_INFO *cellInfo = &wcdmaCellInfo.cell[wcdmaCellInfo.cellNum];

        SCANNERLogDebug("+CRUS: Active SET,%d", crus_info_ptr->active_set_cells_num);
        for (int i = 0; i < crus_info_ptr->active_set_cells_num; i++)
        {
            ACTIVE_SET *active_set = &crus_info_ptr->active_set[i];
            SCANNERLogDebug(",%d,%d,%d,%d,%.1f,%.1f,%d,%d,%d,%d", active_set->cell_psc, active_set->cell_freq, active_set->cell_ssc, active_set->cell_sstd, active_set->cell_totecio, active_set->cell_ecio, active_set->cell_rscp, active_set->umts_sets_cell_tpc, active_set->umts_sets_cell_seccpichovsf, active_set->cell_winsize);

            memcpy(cellInfo->plmn, "46001", 5);
            cellInfo->psc =  active_set->cell_psc;
            cellInfo->arfcn = active_set->cell_freq;
            cellInfo->rscp = active_set->cell_rscp;
            
            wcdmaCellInfo.cellNum++;
            cellInfo++;
        }

        SCANNERLogDebug("+CRUS: Sync Neighbor SET,%d", crus_info_ptr->syncset_cells_nums);
        for (int i = 0; i < crus_info_ptr->syncset_cells_nums; i++)
        {
            NEIGHBOR_SET *active_set = &crus_info_ptr->sync_neighbor_set[i];
            SCANNERLogDebug(",%d,%d,%d,%d,%.1f,%.1f,%d,%d", active_set->cell_psc, active_set->cell_freq, active_set->cell_ssc, active_set->cell_sstd, active_set->cell_totecio, active_set->cell_ecio, active_set->cell_rscp, active_set->cell_winsize);
            
            memcpy(cellInfo->plmn, "46001", 5);
            cellInfo->psc =  active_set->cell_psc;
            cellInfo->arfcn = active_set->cell_freq;
            cellInfo->rscp = active_set->cell_rscp;

            wcdmaCellInfo.cellNum++;
            cellInfo++;
        }
    }
}

void buildWcdmaSnifferResult(MSGHEADER *msgHdr, PCMDHEADER pCmd)
{
    std::string qm = "\"";
    stringstream result;
    //build sniffer result to FEP

    //start
	result << "[";
    //build sniffer report
    WCDMA_CELL_INFO *cellInfo = &wcdmaCellInfo.cell[0];
    for(uint32_t i = 0; i < wcdmaCellInfo.cellNum; i++)
    {
        result << "{";
       	result << qm << "cellNumber" << qm << ":" << 11 << ",";
		result << qm << "plmn" << qm << ":" << cellInfo->plmn << ",";
		result << qm << "arfcn" << qm << ":" << cellInfo->arfcn << ",";
		result << qm << "psc" << qm << ":" << (int32_t)cellInfo->psc << ",";
		result << qm << "rscp" << qm << ":" << (int32_t)cellInfo->rscp << ",";

		result << "}";        

 		if(i == (wcdmaCellInfo.cellNum - 1))  continue;

		result << ",";
    }

    //
	result << "]";
    result << endl;

    if(msgHdr->srcID == MODULE_INTF)
    {
	    CM_SendMsg_1Para(MODULE_INTF, MODULE_SCANNER, MSG_TYPE_COMMAND, CMD_EVENT, CMD_WCDMA_EVT_SNIFF, 0,
					     PARA_TYPE_SNIFFER_RESULT, result.str().length(), (U8 *)result.str().c_str());        
    }
	else
	{
	    CM_SendMsg_1Para(msgHdr->srcID, MODULE_SCANNER, MSG_TYPE_COMMAND, CMD_GET_RESPONSE, pCmd->cmdCode, pCmd->cmdIndex,
                         PARA_TYPE_SNIFFER_RESULT, result.str().length(), (U8 *)result.str().c_str());
	}

    return;
}

bool get_wcdma_cell_info(MSGHEADER *msgHdr, PCMDHEADER pCmd, CRUS_INFO *crus_info)
{
    bool ret = false;
    if (!sc_init_serial(dongle_at_port))
    {
        return false;
    }

    ret = query_wcdma_cell_info(serial_fd, crus_info);
    generateWcdmaSnifferResult(crus_info);

    sc_term_serial();
    return ret;
}

bool get_gsm_cell_info(MONI_INFO *moni_info)
{
    bool ret = false;
    if (!sc_init_serial(dongle_at_port)){
        return false;
    }
    ret = query_gsm_cell_info(serial_fd, moni_info);
    sc_term_serial();
    return ret;
}

void reportScannerHeartBeat(void *h)
{
    U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
    CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_SCANNER, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
        PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc);   
    MOD_timerRestart(scannerheartBeat, SCANNER_HB_INTERVAL);
}

void buildAndSendTlvCmdSetScannerResponseMsg(MSGHEADER *msgHdr, PCMDHEADER pCmd, U32 result, U32 paraType, U32 paraValue)
{
    U8 cmdResponse = (pCmd->cmdType & 0xf) | 0x10;
   
    if(result == PARA_VALUE_RESULT_FAILED)
    {
        CM_SendMsg_2Para(msgHdr->srcID, MODULE_SCANNER, MSG_TYPE_COMMAND, cmdResponse, pCmd->cmdCode, pCmd->cmdIndex,
                         PARA_TYPE_RESULT, 4, (U8 *)&result, paraType, 4, (U8 *)&paraValue);
    }
    else
    {
        CM_SendMsg_1Para(msgHdr->srcID, MODULE_SCANNER, MSG_TYPE_COMMAND, cmdResponse, pCmd->cmdCode, pCmd->cmdIndex,
                         PARA_TYPE_RESULT, 4, (U8 *)&result);
    }    
}

void handleScannerTlvCmdSetMsg(MSGHEADER *msgHdr, PCMDHEADER pCmd)
{
    memset(&wcdmaCellInfo, 0, sizeof(WcdmaSnifferResult));
    memset(&lteCellInfo, 0, sizeof(LteSnifferResult));    

    CRUS_INFO crus_info;
    memset(&crus_info, 0x0, sizeof(CRUS_INFO));
    
    MONI_INFO  moni_info;
    memset(&moni_info, 0x0, sizeof(MONI_INFO));

    switch(pCmd->cmdCode)
    {
        case CMD_WCDMA_DO_SNIFFER:
            {
                if(get_wcdma_cell_info(msgHdr, pCmd, &crus_info))
                {
                    if(msgHdr->srcID == MODULE_INTF)
                    {
                        buildWcdmaSnifferResult(msgHdr, pCmd);
                    }
                    buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_SUCCESS, 0, 0);

                }
                else
                {
                    buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_GENERAL_ERROR);
                }

                break;
            }
        case CMD_LTE_DO_SNIFFER:
            {
                if(get_lte_cell_info(msgHdr, pCmd))
                {
                    if(msgHdr->srcID == MODULE_INTF)
                    {                    
                       //send sniffer result
                       buildLteSniffResult(msgHdr, pCmd);
                    }
                    buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_SUCCESS, 0, 0);

                }
                else
                {
                    buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_GENERAL_ERROR);
                }

                break;
            }

        case CMD_SCANNER_GSM_DO_SNIFFER:
            {
                if (get_gsm_cell_info(&moni_info))
                {
                    if(msgHdr->srcID == MODULE_INTF)
                    {
                        buildWcdmaSnifferResult(msgHdr, pCmd);
                    }
                    buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_SUCCESS, 0, 0);

                }
                else
                {
                    buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_GENERAL_ERROR);
                }
            
                break;
            }

        default:
            buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_GENERAL_ERROR);
            SCANNERLogError("Unknown event cmdCode=%04x",pCmd->cmdCode);
            break;
    }
}

void handleScannerTlvCmdGetMsg(MSGHEADER *msgHdr, PCMDHEADER pCmd)
{
    switch(pCmd->cmdCode)
    {
        case CMD_GET_LTE_RESULT:
            buildLteSniffResult(msgHdr, pCmd);
            break;
        case CMD_GET_WCDMA_RESULT:
            buildWcdmaSnifferResult(msgHdr, pCmd);
            break;
        default:
            buildAndSendTlvCmdSetScannerResponseMsg(msgHdr, pCmd, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_GENERAL_ERROR);
            SCANNERLogError("Unknown event cmdCode=%04x",pCmd->cmdCode);
            break;
    }
}

void handleScannerTlvCmdEventMsg(MSGHEADER *msgHdr, PCMDHEADER pCmd)
{
    switch(pCmd->cmdCode)
    {
        default:
            SCANNERLogError("Unknown event cmdCode=%04x",pCmd->cmdCode);
            break;
    }
}

void handleScannerTlvCmdMsg(MSGHEADER *msgHdr, U8 *payload)
{
    PCMDHEADER pCmd = (PCMDHEADER) payload;

    switch (pCmd->cmdType)
    {
        case CMD_SET:
            handleScannerTlvCmdSetMsg(msgHdr, pCmd);
            break;
        case CMD_GET:
            handleScannerTlvCmdGetMsg(msgHdr, pCmd);
            break;
        case CMD_EVENT:
            handleScannerTlvCmdEventMsg(msgHdr, pCmd); 
            break;
        default:
            SCANNERLogError("Unknown CmdType = %x",  pCmd->cmdType);
            break;
    }
}
void handleScannerTlvTimeTick()
{
    MOD_timerProc(MODULE_SCANNER);
}

void scanner_tlv_msg_handler()
{
    MSGHEADER msgHdr;
    U8 payload[MAX_MSG_SIZE];
      
    while(1)
    {
        if( MSG_read(MODULE_SCANNER, &msgHdr, (void *)payload) != 0 )
        {
            //dbgprintf(DEBUG_ERROR, stderr, "internal_msg_thread:MSG_read error. \n");
            continue;
        }
    
        if( MODULE_SCANNER != msgHdr.dstID )
        {
            SCANNERLogError("received a wrong tlv msg id = %d ", msgHdr.dstID);
            continue;
        }
        
        SCANNERLogDebug("received tlv msg id = %d ", msgHdr.srcID);
        switch ( msgHdr.msgType )
        {
            case MSG_TYPE_COMMAND:
                handleScannerTlvCmdMsg(&msgHdr, payload);
                break;
            case MSG_TYPE_TICK:
                handleScannerTlvTimeTick();
                break;
            case MSG_TYPE_INTERNAL:
                break;
            default:
              SCANNERLogError("Unknown msg type %x\n ", msgHdr.msgType);
              break;
        }
    }
}

static void* Scanner_main(void *arg __attribute__((unused)))
{
    pthread_setname_np(pthread_self(), "scanner");

    scannerheartBeat = MOD_timerStart(MODULE_SCANNER,SCANNER_HB_INTERVAL,reportScannerHeartBeat,NULL);

    scanner_tlv_msg_handler();

    pthread_exit((void*)0);
}

RESULT SCANNER_init()
{
    pthread_t scanner_thread;

    if( RC_OK != MOD_register(&modScannerInfo) )
    {
        SCANNERLogError("Can't register gps module with syscore\n");
        return RC_FAIL;
    }

    pthread_create(&scanner_thread, NULL, Scanner_main, 0);

    return RC_OK;
}

